home *** CD-ROM | disk | FTP | other *** search
/ World of Sound / World of Sound.iso / utils / modplayers / tracker / hpux_audio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-11  |  8.1 KB  |  357 lines

  1. /* hp_audio.c */
  2.  
  3. /* $Id: hpux_audio.c,v 1.1 1993/07/14 16:33:41 espie Exp espie $
  4.  * $Log: hpux_audio.c,v $
  5.  * Revision 1.1  1993/07/14  16:33:41  espie
  6.  * Initial revision
  7.  *
  8.  */
  9.  
  10. #include <malloc.h>
  11. #include <stdio.h>
  12. #include "defs.h"
  13. #include "extern.h"
  14. #include <audio/Alib.h>
  15. #include <sys/socket.h>
  16. #include <netinet/in.h>
  17. #include <netinet/tcp.h>
  18.  
  19. LOCAL char *id = "$Id: hpux_audio.c,v 1.1 1993/07/14 16:33:41 espie Exp espie $";
  20.  
  21.  
  22. Audio    *audio;        /* AUDIO connection for Alib, like DISPLAY for Xlib */
  23.  
  24. LOCAL BOOL stereo;        /* are we playing stereo or not? */
  25. LOCAL int freq;            /* which frequency do we want? */
  26.  
  27. LOCAL int primary, secondary;    /* 256th of primary/secondary source for */
  28.                 /* that side. */
  29. AErrorHandler    prevHandler;    /* pointer to previous handler */    
  30.  
  31. LOCAL Bool    audioPaused = True;
  32. LOCAL int    streamSocket = 0;
  33. LOCAL int    pauseCount;
  34.  
  35. LOCAL short    *inBuf = NULL, *bufBase = NULL;
  36. LOCAL int    inBufIndex = 0;
  37. LOCAL long    inLen;
  38.  
  39. LOCAL ATransID    xid;
  40.  
  41. LOCAL AConvertParams    *convert_params;
  42.  
  43. LOCAL AudioAttrMask    AttribsMask = 0, PlayAttribsMask = 0, ignoredMask = 0;
  44. LOCAL AudioAttributes    Attribs, PlayAttribs;
  45. LOCAL AGainEntry    gainEntry[4];    /* Need to be global since */
  46.                     /* PlayAttribs is global and it */
  47.                     /* contains a pointer to gainEntry */
  48. LOCAL SSPlayParams    streamParams;
  49.  
  50.  
  51.  
  52. long myErrorHandler(audio, err_event)
  53.     Audio        *audio;
  54.     AErrorEvent    *err_event;
  55. {
  56.     char    errorbuf[132];
  57.  
  58.     AGetErrorText(audio, err_event->error_code, errorbuf, 131);
  59.     fprintf(stderr, "tracker: %s\n", errorbuf);
  60.  
  61.     exit(1);
  62. }
  63.  
  64.  
  65. void set_mix(percent)
  66. int percent;
  67. {
  68.     percent = (percent * 256) / 100;
  69.     primary = percent;
  70.     secondary = 512 - percent;
  71. }
  72.  
  73.  
  74. void create_playstream()
  75. {
  76.     LOCAL SStream    audioStream;
  77.  
  78.     /*
  79.      * Initiate transaction.
  80.      */
  81.     xid = APlaySStream(audio, ~0, &PlayAttribs, &streamParams,
  82.                &audioStream, NULL);
  83.  
  84.     /*
  85.      * Create a stream socket.
  86.      */
  87.     streamSocket = socket(AF_INET, SOCK_STREAM, 0);
  88.     if(streamSocket < 0) {
  89.     perror("Socket creation failed");
  90.     exit(1);
  91.     }
  92.   
  93.     /*
  94.      * Connect the stream socket to the audio stream port.
  95.      */
  96.     if (connect(streamSocket,
  97.         (struct sockaddr *)&audioStream.tcp_sockaddr,
  98.         sizeof(struct sockaddr_in)) < 0) {
  99.     perror( "Connect failed" );
  100.     exit(1);
  101.     }
  102. }  
  103.  
  104.  
  105. int open_audio(f, s)
  106. int f;
  107. BOOL s;
  108. {
  109.     char        *pSpeaker;
  110.     int            useIntSpeaker;
  111.     int            seekOffset, data_length;
  112.     AByteOrder        play_byte_order, byte_order;
  113.  
  114.  
  115.     audio = AOpenAudio(NULL, NULL);
  116.  
  117.     if (!audio) {
  118.         perror("Error opening audio device");
  119.     end_all();
  120.     }
  121.  
  122.     /* replace default error handler */
  123.     prevHandler = ASetErrorHandler(myErrorHandler);
  124.  
  125.     stereo = s;
  126.     if (stereo) {
  127.         Attribs.attr.sampled_attr.channels = 2;
  128.         AttribsMask |= (AttribsMask | ASChannelsMask);
  129.     }
  130.  
  131.     /*
  132.      * Get the best attributes from the server?
  133.      */
  134.     if (f <= 0) {
  135.     AudioAttributes    *bestAttr;
  136.  
  137.     bestAttr = ABestAudioAttributes(audio);
  138.     freq = bestAttr->attr.sampled_attr.sampling_rate;
  139.     } else
  140.     freq = f;
  141.  
  142.     PlayAttribs.attr.sampled_attr.sampling_rate = freq;
  143.     PlayAttribsMask |= ASSamplingRateMask;
  144.  
  145.     Attribs.attr.sampled_attr.sampling_rate = freq;
  146.     AttribsMask |= ASSamplingRateMask;
  147.  
  148.     AChooseSourceAttributes(audio, NULL, NULL, AFFRawLin16,
  149.                 AttribsMask, &Attribs, &seekOffset,
  150.                 &data_length, &byte_order, NULL);
  151.  
  152.     AChoosePlayAttributes(audio, &Attribs, PlayAttribsMask,
  153.               &PlayAttribs, &play_byte_order, NULL);
  154.  
  155.     /*
  156.      * Prepare for conversion.
  157.      * Must remember to free convert_params by calling AEndConversion.
  158.      */
  159.     convert_params = ASetupConversion(audio, &Attribs, &byte_order,
  160.                       &PlayAttribs, &play_byte_order, NULL);
  161.  
  162.     pSpeaker = getenv("SPEAKER");    /* get user speaker preference */
  163.     if (pSpeaker) {
  164.     useIntSpeaker = (*pSpeaker == 'i' || *pSpeaker == 'I');
  165.     } else {
  166.     /*
  167.      * SPEAKER env.var not found - use internal speaker.
  168.      */  
  169.     useIntSpeaker = 1;
  170.     }
  171.  
  172.     switch (PlayAttribs.attr.sampled_attr.channels) {
  173.  
  174.     case 1:    /* Mono */
  175.     gainEntry[0].u.o.out_ch = AOCTMono;
  176.     gainEntry[0].gain = AUnityGain;
  177.     gainEntry[0].u.o.out_dst
  178.         = (useIntSpeaker) ? AODTMonoIntSpeaker : AODTMonoJack;
  179.     break;
  180.  
  181.     case 2:    /* Stereo */
  182.     default:
  183.     gainEntry[0].u.o.out_ch = AOCTLeft;
  184.     gainEntry[0].gain = AUnityGain;
  185.     gainEntry[0].u.o.out_dst
  186.         = (useIntSpeaker) ? AODTLeftIntSpeaker : AODTLeftJack;
  187.     gainEntry[1].u.o.out_ch = AOCTRight;
  188.     gainEntry[1].gain = AUnityGain;
  189.     gainEntry[1].u.o.out_dst
  190.         = (useIntSpeaker) ? AODTRightIntSpeaker : AODTRightJack;
  191.     break;
  192.     }
  193.     streamParams.gain_matrix.type = AGMTOutput;    /* gain matrix */
  194.     streamParams.gain_matrix.num_entries
  195.     = PlayAttribs.attr.sampled_attr.channels;
  196.     streamParams.gain_matrix.gain_entries = gainEntry;
  197.     streamParams.play_volume = AUnityGain;    /* play volume */
  198.     streamParams.priority = APriorityNormal;    /* normal priority */
  199.     streamParams.event_mask = 0;        /* don't solicit any events */
  200.  
  201.     /*
  202.      * Create an audio stream.
  203.      */
  204.     create_playstream();
  205.  
  206.     /*
  207.      * Calculate the required buffer size for the data prior to conversion
  208.      * and allocate memory for the pre-converted data.
  209.      */
  210.     inLen = ACalculateLength(audio, audio->block_size,
  211.                  &PlayAttribs, &Attribs, NULL); 
  212.     inBuf = malloc(inLen);
  213.     inBufIndex = 0;
  214.  
  215.     /*
  216.      * Allocate a buffer for the converted data.
  217.      */
  218.     bufBase = malloc(inLen);
  219.  
  220.     /*
  221.      * Start stream paused so we can transfer enough data (3 seconds worth)
  222.      * before playing starts to prevent stream from running out.
  223.      */
  224.     APauseAudio(audio, xid, NULL, NULL);
  225.     pauseCount = 3
  226.         * PlayAttribs.attr.sampled_attr.channels
  227.         * PlayAttribs.attr.sampled_attr.sampling_rate
  228.         * (PlayAttribs.attr.sampled_attr.bits_per_sample >> 3);
  229.     audioPaused = True;
  230.  
  231.     freq = PlayAttribs.attr.sampled_attr.sampling_rate;
  232.  
  233.     if (freq != f)
  234.     fprintf(stderr, "\nFrequency used is %d\n", freq);
  235.  
  236.     set_mix(30);
  237.  
  238.     return freq;
  239. }
  240.  
  241.  
  242. void output_samples(left, right)
  243. int left, right;
  244. {
  245.     if (inBufIndex > inLen - 2)
  246.     flush_buffer();
  247.  
  248.     if (stereo) {
  249.         inBuf[inBufIndex++] = (left * primary + right * secondary) / 256;
  250.         inBuf[inBufIndex++] = (right * primary + left * secondary) / 256;
  251.     } else {
  252.         inBuf[inBufIndex++] = left + right;
  253.     }
  254. }
  255.  
  256.  
  257. void discard_buffer()
  258. {
  259.     /*
  260.      * Destroy old playstream.
  261.      */
  262.     AStopAudio(audio, xid, ASMThisTrans, NULL, NULL);
  263.     close(streamSocket);
  264.     streamSocket = 0;
  265.  
  266.     /*
  267.      * Recreate new playstream.
  268.      */
  269.     create_playstream();
  270.     inBufIndex = 0;
  271. }
  272.  
  273.  
  274. void flush_buffer()
  275. {
  276.     int        len_written = 0, len, bytes_written, bytes_read;
  277.     short    *buf = inBuf;
  278.  
  279.     /*
  280.      * Convert buffer
  281.      */
  282.     AConvertBuffer(audio, convert_params, inBuf, inBufIndex * sizeof(short),
  283.            bufBase, inLen, &bytes_read, &bytes_written, NULL);
  284.     len = bytes_written;
  285.     buf = bufBase;    
  286.  
  287.     /*
  288.      * Write the converted data to the stream socket
  289.      */
  290.     while (len) {
  291.         /*
  292.      * write converted data to stream socket until we have emptied buffer
  293.      */
  294.     if ((len_written = write(streamSocket, buf, len)) < 0) {
  295.         perror("write failed");
  296.         exit(1);
  297.         }
  298.     buf += len_written;
  299.     len -= len_written;
  300.  
  301.     if (audioPaused) {
  302.         pauseCount -= len_written;
  303.         if (len_written == 0 || pauseCount <= 0) {
  304.         AResumeAudio(audio, xid, NULL, NULL);
  305.         audioPaused = False;
  306.         }
  307.     }
  308.     }
  309.     inBufIndex = 0;
  310. }
  311.  
  312.  
  313. void close_audio()
  314. {
  315.     int        bytes_written;
  316.  
  317.  
  318.     if (audioPaused) {
  319.     AResumeAudio(audio, xid, NULL, NULL);
  320.     }
  321.     /*
  322.      * Free the convert_params structure and flush out
  323.      * the conversion pipeline
  324.      */
  325.     AEndConversion(audio, convert_params, bufBase,
  326.            audio->block_size, &bytes_written, NULL);
  327.  
  328.     ASetCloseDownMode(audio, AKeepTransactions, NULL);
  329.     ASetErrorHandler(prevHandler);
  330.     ACloseAudio(audio, NULL);
  331.  
  332.     if (streamSocket)    close(streamSocket);
  333.     if (inBuf)        free(inBuf);
  334.     if (bufBase)    free(bufBase);
  335.  
  336.     exit(0);
  337. }
  338.  
  339.  
  340. int update_frequency()
  341. {
  342.     /* not implemented */
  343.     return 0;
  344. }
  345.  
  346.  
  347. void set_synchro(sync)
  348. BOOL sync;
  349. {
  350.     if (streamSocket) {
  351.     if (sync)
  352.         setsockopt(streamSocket, SOL_SOCKET, TCP_NODELAY, 1);
  353.     else
  354.         setsockopt(streamSocket, SOL_SOCKET, TCP_NODELAY, 0);
  355.     }
  356. }
  357.